PlanStatus = {
  PASSING: 0,
  FAILING: 1,
  UNKNOWN: 2,
  DISABLED: 3,
  ENABLED: 4,
  IGNORED: 5,
  NOT_IGNORED: 6
};

//scheme : string, host : string, username : optional string , password : optional string
function Server(scheme, host, username, password) {
  this.scheme = scheme;
  this.host = host;
  this.username = username;
  this.password = password;
  this.plans = [];
}

Server.prototype.authenticateCallback = function(request) {
  if (request.readyState == 4 && request.status == 200) {
    var parser = new DOMParser();
    var xmlDoc = parser.parseFromString(request.responseText, "text/xml");    
    for (var i = 0; i < this.plans.length; ++i) {
      var plan = this.plans[i];
      try {
        plan.disabled = (plan.extractIsDisabled(xmlDoc)) ? PlanStatus.DISABLED : PlanStatus.ENABLED;
        updateBadge();
      } catch (e) {}
      if (plan.disabled == PlanStatus.ENABLED && plan.ignored !== PlanStatus.IGNORED) {
        plan.checkForFailure();
      }
    }
  }
};

Server.prototype.authenticate = function() {
  var xmlHttpRequest = new XMLHttpRequest();
  var server = this;
  xmlHttpRequest.onreadystatechange = function() { server.authenticateCallback(xmlHttpRequest); };
  xmlHttpRequest.open("GET", this.getBaseRestUri() + "plan?os_authType=basic", true);
  xmlHttpRequest.send();
};

Server.prototype.listPlans = function(callback) {
  var xmlHttpRequest = new XMLHttpRequest();
  var server = this;
  xmlHttpRequest.onreadystatechange = function() { if (xmlHttpRequest.readyState == 4) { callback(xmlHttpRequest);  }};
  xmlHttpRequest.open("GET", this.getBaseRestUri() + "plan?os_authType=basic", true);
  xmlHttpRequest.send();
};

//plan : Plan
Server.prototype.addPlan = function(plan) {
  this.plans.push(plan);
};

Server.prototype.getBaseRestUri = function() {
  var userString = (this.username === undefined) ? "" : this.username + ":" + this.password + "@";
  return this.scheme + "://" + userString + this.host + "/rest/api/latest/";
};

//server : Server, planName : string, passing : PlanStatus, disabled : PlanStatus
function Plan(server, planName, passing, disabled, ignored) {
  if (passing === undefined) {
    passing = PlanStatus.UNKNOWN;
  }
  if (disabled === undefined) {
    disabled = PlanStatus.UNKNOWN;
  }
  if (ignored === undefined) {
    ignored = PlanStatus.NOT_IGNORED;
  }
  this.server = server;
  this.planName = planName;
  this.passing = passing;
  this.disabled = disabled;
  this.ignored = ignored;
}

Plan.prototype.toJSON = function() {
  return {planName: this.planName, passing: this.passing, disabled: this.disabled, ignored: this.ignored};
}

Plan.prototype.isDisabled = function() {
  return (this.disabled === PlanStatus.DISABLED);
}

//xmlDoc : Document
Plan.prototype.extractIsDisabled = function(xmlDoc) {
  doc = xmlDoc;
  
  var plans = xmlDoc.documentElement.getElementsByTagName("plan");
  for (var plan in plans) {
    if (plans[plan].getAttribute("key") == this.planName) {
      return disabled = (plans[plan].getAttribute("enabled") == "false");
    }
  }
  return false;
}

Plan.prototype.checkForFailure = function() {
  var xmlHttpRequest = new XMLHttpRequest();
  var plan = this;
  xmlHttpRequest.onreadystatechange = function() { plan.checkForFailureCallback(xmlHttpRequest); };
  xmlHttpRequest.open("GET", this.server.getBaseRestUri() + "build/" + this.planName + "/latest", true);
  xmlHttpRequest.send();
};

Plan.prototype.checkForFailureCallback = function(request) {
  if (request.readyState == 4 && request.status == 200) {
    response = request.responseText;
    var parser = new DOMParser();
    var xmlDoc = parser.parseFromString(request.responseText, "text/xml");
    try {
      var failedTests = parseInt(xmlDoc.getElementsByTagName("failedTestCount")[0].textContent, 10);
      if (failedTests !== 0) {
        if (this.passing == PlanStatus.PASSING) {
          notifyOfFailure(this.planName, this.server);
        }
        this.passing = PlanStatus.FAILING;
      } else {
        this.passing = PlanStatus.PASSING;
      }
      updateBadge();
    } catch (e) {}
  }
};

Plan.prototype.getStatusText = function() {
  if (this.ignored === PlanStatus.IGNORED) {
    return "Ignored";
  }
  if (this.disabled === PlanStatus.DISABLED) {
    return "Disabled";
  }
  switch (this.passing) {
    case PlanStatus.PASSING:
      return "Passing";
    case PlanStatus.FAILING:
      return "Failing";
    case PlanStatus.UNKNOWN:
      return "Unknown";
  }
};

Plan.prototype.toggleIgnore = function() {
  if (this.ignored !== PlanStatus.IGNORED) {
    this.ignored = PlanStatus.IGNORED;
  } else {
    this.ignored = PlanStatus.NOT_IGNORED;
  }
}

function getServerDetailsFromLocalStorage() {
  if (localStorage["updateInterval"] === undefined) {
    localStorage["updateInterval"] = 5;
  }
  updateInterval = localStorage["updateInterval"];
      
  tempServers = (localStorage["servers"] === undefined) ? [] : JSON.parse(localStorage["servers"]);
  servers = [];

  for (var s = 0; s < tempServers.length; ++s) {
    var tempServer = tempServers[s];
    var server = new Server(tempServer.scheme, tempServer.host, tempServer.username, tempServer.password);
    for (var p = 0; p < tempServer.plans.length; ++p) {
      var plan = tempServer.plans[p];
      server.addPlan(new Plan(server, plan.planName, plan.passing, plan.disabled, plan.ignored));
    }
    servers.push(server);
  }
  return servers;
}

function saveServersAndPingBackgroundPage(servers) {
  localStorage["servers"] = JSON.stringify(servers);
  chrome.extension.getBackgroundPage().updateServerDetailsFromLocalStorage();
}